For more details, see Software and Package Versions.
Run drop down (top right of the
code pane) and click Run Allknit (top left of code
pane) and a file will be generated in docs/index.htmlInstall R packages if needed.
# Required packages
required_packages <- c(
"rmarkdown",
"bookdown",
"knitr",
"tidyverse",
"purrr",
"glue",
"lubridate",
"scales",
"patchwork",
"DiagrammeR",
"DiagrammeRsvg",
"webshot2",
"magick",
"rsvg",
"sf",
"tmap",
"ggspatial",
"prettymapr",
"units",
"boot"
)
# Try to install packages if not installed
default_options <- options()
tryCatch(
{
# Disable interactivity
options(install.packages.compile.from.source = "always")
# Install package if not installed
for (package in required_packages) {
is_package_installed <- require(package, character.only = TRUE)
if (!is_package_installed) {
cat(paste0("Installing package: ", package, "\n"))
install.packages(package)
} else {
cat(paste0("Package already installed: ", package, "\n"))
}
}
},
error = function(cond) {
stop(cond)
},
finally = {
options(default_options) # reset interactivity
}
)Load R libraries.
Read data from the data folder.
Bikeways data with manually verified (Google Street View/Earth and Web Search) painted lanes and cycle tracks for Vancouver, Canada
# Read data
vancbike_raw <- read_sf("../data/vancouver-bikeways-2024-06-02.geojson")
# Get download date
vancbike_dldate <- ddesc %>% filter(
file == "vancouver-bikeways-2024-06-02.geojson"
) %>% pull(download_date)Only the first 1000 records are shown.
The data contains the following columns:
## Simple feature collection with 3666 features and 22 fields
## Geometry type: LINESTRING
## Dimension: XY
## Bounding box: xmin: -123.2238 ymin: 49.19899 xmax: -123.0233 ymax: 49.31428
## Geodetic CRS: WGS 84
## # A tibble: 3,666 × 23
## id street status road_type road_type_recode install_year install_type
## <chr> <chr> <chr> <chr> <chr> <dbl> <chr>
## 1 294725 Highbury Active Resident… Local 2006 Local Street
## 2 294726 Highbury Active Resident… Local 2006 Local Street
## 3 294731 W 8th Ave Active Resident… Local 1994 Local Street
## 4 294732 W 8th Ave Active Resident… Local 1994 Local Street
## 5 294733 Off Street Active Lane Local 2003 Protected B…
## 6 294736 W 5th Ave Active Resident… Local 2009 Local Street
## 7 294737 W 8th Ave Active Resident… Local 1994 Local Street
## 8 294738 W 7th Ave Active Resident… Local 1994 Local Street
## 9 294739 W 7th Ave Active Resident… Local 1994 Local Street
## 10 294742 W 7th Ave Active Resident… Local 1994 Local Street
## # ℹ 3,656 more rows
## # ℹ 16 more variables: verify_install_year <dbl>, verify_install_date <chr>,
## # verify_install_type <chr>, verify_install_comment <chr>,
## # verify_upgrade1_year <dbl>, verify_upgrade1_date <chr>,
## # verify_upgrade1_type <chr>, verify_upgrade1_comment <chr>,
## # verify_upgrade2_year <dbl>, verify_upgrade2_date <chr>,
## # verify_upgrade2_type <chr>, verify_upgrade2_comment <chr>, …
The data files are available below:
Bikeways data with manually verified (Google Street View/Earth and Web Search) painted lanes and cycle tracks for Calgary, Canada
# Read data
calgbike_raw <- read_sf("../data/calgary-bikeways-2024-06-05.geojson")
# Get download date
calgbike_dldate <- ddesc %>% filter(
file == "calgary-bikeways-2024-06-05.geojson"
) %>% pull(download_date)Only the first 1000 records are shown.
The data contains the following columns:
## Simple feature collection with 4169 features and 21 fields
## Geometry type: MULTILINESTRING
## Dimension: XY
## Bounding box: xmin: -114.269 ymin: 50.89762 xmax: -113.9302 ymax: 51.17778
## Geodetic CRS: WGS 84
## # A tibble: 4,169 × 22
## id street status road_type road_type_recode install_year install_type
## <chr> <chr> <chr> <chr> <chr> <dbl> <chr>
## 1 1 <NA> EXISTING <NA> <NA> 2003 On-Street Bike…
## 2 2 <NA> EXISTING <NA> <NA> 2009 On-Street Bike…
## 3 3 <NA> EXISTING <NA> <NA> 2009 On-Street Bike…
## 4 4 <NA> EXISTING <NA> <NA> 1999 On-Street Bike…
## 5 5 <NA> EXISTING <NA> <NA> 1999 On-Street Bike…
## 6 6 <NA> EXISTING <NA> <NA> 2005 On-Street Bike…
## 7 7 <NA> EXISTING <NA> <NA> 1999 On-Street Bike…
## 8 8 <NA> EXISTING <NA> <NA> 1999 On-Street Bike…
## 9 9 <NA> EXISTING <NA> <NA> 1999 On-Street Bike…
## 10 10 <NA> INACTIVE <NA> <NA> NA DECOMMISSIONED
## # ℹ 4,159 more rows
## # ℹ 15 more variables: verify_install_year <dbl>, verify_install_date <chr>,
## # verify_install_type <chr>, verify_install_comment <chr>,
## # verify_upgrade1_year <dbl>, verify_upgrade1_date <chr>,
## # verify_upgrade1_type <chr>, verify_upgrade1_comment <chr>,
## # verify_upgrade2_year <dbl>, verify_upgrade2_date <chr>,
## # verify_upgrade2_type <chr>, verify_upgrade2_comment <chr>, …
The data files are available below:
Bikeways data with manually verified (Google Street View/Earth and Web Search) painted lanes and cycle tracks for Toronto, Canada
# Read data
toronbike_raw <- read_sf("../data/toronto-bikeways-2024-06-02.geojson")
# Get download date
toronbike_dldate <- ddesc %>% filter(
file == "toronto-bikeways-2024-06-02.geojson"
) %>% pull(download_date)Only the first 1000 records are shown.
The data contains the following columns:
## Simple feature collection with 1323 features and 22 fields
## Geometry type: MULTILINESTRING
## Dimension: XY
## Bounding box: xmin: -79.63039 ymin: 43.58221 xmax: -79.11803 ymax: 43.85546
## Geodetic CRS: WGS 84
## # A tibble: 1,323 × 23
## id street street_from street_to road_type road_type_recode install_year
## <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
## 1 8 Bloor St… Parliament… Castle F… Major Ar… Arterial 2001
## 2 17 Lake Sho… Humber Bay… Humber B… Major Ar… Arterial 2001
## 3 18 Lake Sho… 37 M E Fle… Humber B… Major Ar… Arterial 2001
## 4 19 Lake Sho… 50.7 M E L… 37 M E F… Major Ar… Arterial 2001
## 5 38 Queens Q… Martin Goo… Bathurst… Collector Collector 2001
## 6 39 Davenpor… Cottingham… Macphers… Minor Ar… Arterial 2001
## 7 40 Elizabet… College St Gerrard … Collector Collector 2001
## 8 41 Gerrard … Yonge St Church St Minor Ar… Arterial 2001
## 9 42 Macphers… Davenport … Poplar P… Collector Collector 2001
## 10 43 Lake Sho… Marine Par… Palace P… Major Ar… Arterial 2001
## # ℹ 1,313 more rows
## # ℹ 16 more variables: install_type <chr>, verify_install_year <dbl>,
## # verify_install_date <chr>, verify_install_type <chr>,
## # verify_install_comment <chr>, verify_upgrade1_year <dbl>,
## # verify_upgrade1_date <chr>, verify_upgrade1_type <chr>,
## # verify_upgrade1_comment <chr>, verify_upgrade2_year <dbl>,
## # verify_upgrade2_date <chr>, verify_upgrade2_type <chr>, …
The data files are available below:
KSI (2006-2022) data from the Toronto Police Service (TPS) Public Safety Data Portal for Toronto, Ontario
# Read data
ksi_raw <- read_sf("../data/toronto-ksi-2024-06-01.geojson")
# Get download date
ksi_dldate <- ddesc %>% filter(
file == "toronto-ksi-2024-06-01.geojson"
) %>% pull(download_date)Note: Due to the large number of records, only the latest year of 2023 is displayed (n = 695).
The data contains the following columns:
## Simple feature collection with 18957 features and 52 fields
## Geometry type: POINT
## Dimension: XY
## Bounding box: xmin: -79.63839 ymin: 43.58968 xmax: -79.12297 ymax: 43.85545
## Geodetic CRS: WGS 84
## # A tibble: 18,957 × 53
## OBJECTID INDEX_ ACCNUM DATE TIME STREET1 STREET2 OFFSET
## <int> <chr> <chr> <dttm> <chr> <chr> <chr> <chr>
## 1 1 3389067 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 2 2 3389068 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 3 3 3389069 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 4 4 3389070 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 5 5 3389071 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 6 6 3389072 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 7 7 3389073 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 8 8 3389074 893184 2006-01-01 05:00:00 236 WOODBINE AVE O CONN… <NA>
## 9 9 3433023 909646 2006-01-01 05:00:00 315 DANFORTH AVE WEST L… <NA>
## 10 10 3433024 909646 2006-01-01 05:00:00 315 DANFORTH AVE WEST L… <NA>
## # ℹ 18,947 more rows
## # ℹ 45 more variables: ROAD_CLASS <chr>, DISTRICT <chr>, LATITUDE <dbl>,
## # LONGITUDE <dbl>, ACCLOC <chr>, TRAFFCTL <chr>, VISIBILITY <chr>,
## # LIGHT <chr>, RDSFCOND <chr>, ACCLASS <chr>, IMPACTYPE <chr>, INVTYPE <chr>,
## # INVAGE <chr>, INJURY <chr>, FATAL_NO <int>, INITDIR <chr>, VEHTYPE <chr>,
## # MANOEUVER <chr>, DRIVACT <chr>, DRIVCOND <chr>, PEDTYPE <chr>,
## # PEDACT <chr>, PEDCOND <chr>, CYCLISTYPE <chr>, CYCACT <chr>, …
The data files are available below:
parsed <- list()
msg <- list()
bikeways <- list(
Vancouver = vancbike_raw,
Calgary = calgbike_raw,
Toronto = toronbike_raw
)
for (city in names(bikeways)) {
# Filter for verified bikeways only
df <- bikeways[[city]] %>%
filter(
!is.na(verify_install_year) |
!is.na(verify_upgrade1_year) |
!is.na(verify_upgrade2_year)
)
# Filter out non verified
if (city == "Vancouver") {
df <- df %>%
filter(is.na(no_verify_install_type))
}
# Try to parse install dates
df <- df %>%
as_tibble %>%
mutate(
clean_date = str_to_lower(
str_replace_all(
verify_install_date,
"[^[:alnum:]]",
" "
)
),
parsed_date = ymd(clean_date) %>%
coalesce(ydm(clean_date)) %>%
coalesce(mdy(clean_date)) %>%
coalesce(myd(clean_date)) %>%
coalesce(dmy(clean_date)) %>%
coalesce(dym(clean_date)),
parsed_month = if_else(
!str_starts(str_trim(clean_date), "pre") & is.na(parsed_date),
yq(clean_date) %>%
coalesce(ym(clean_date)) %>%
coalesce(my(clean_date)),
NA
)
) %>%
rename(
clean_install_date = clean_date,
parsed_install_date = parsed_date,
parsed_install_month = parsed_month
)
# Try to parse upgrade 1 dates
df <- df %>%
as_tibble %>%
mutate(
clean_date = str_to_lower(
str_replace_all(
verify_upgrade1_date,
"[^[:alnum:]]",
" "
)
),
parsed_date = ymd(clean_date) %>%
coalesce(ydm(clean_date)) %>%
coalesce(mdy(clean_date)) %>%
coalesce(myd(clean_date)) %>%
coalesce(dmy(clean_date)) %>%
coalesce(dym(clean_date)),
parsed_month = if_else(
!str_starts(str_trim(clean_date), "pre") & is.na(parsed_date),
yq(clean_date) %>%
coalesce(ym(clean_date)) %>%
coalesce(my(clean_date)),
NA
)
) %>%
rename(
clean_upgrade1_date = clean_date,
parsed_upgrade1_date = parsed_date,
parsed_upgrade1_month = parsed_month
)
# Try to parse upgrade 1 dates
df <- df %>%
as_tibble %>%
mutate(
clean_date = str_to_lower(
str_replace_all(
verify_upgrade2_date,
"[^[:alnum:]]",
" "
)
),
parsed_date = ymd(clean_date) %>%
coalesce(ydm(clean_date)) %>%
coalesce(mdy(clean_date)) %>%
coalesce(myd(clean_date)) %>%
coalesce(dmy(clean_date)) %>%
coalesce(dym(clean_date)),
parsed_month = if_else(
!str_starts(str_trim(clean_date), "pre") & is.na(parsed_date),
yq(clean_date) %>%
coalesce(ym(clean_date)) %>%
coalesce(my(clean_date)),
NA
)
) %>%
rename(
clean_upgrade2_date = clean_date,
parsed_upgrade2_date = parsed_date,
parsed_upgrade2_month = parsed_month
)
# Num of records with install or upgrade dates
n_idates <- df %>% filter(!is.na(verify_install_date)) %>% nrow
n_u1dates <- df %>% filter(!is.na(verify_upgrade1_date)) %>% nrow
n_u2dates <- df %>% filter(!is.na(verify_upgrade2_date)) %>% nrow
# Num of records with parsed dates and months
n_pidates <- df %>% filter(!is.na(parsed_install_date)) %>% nrow
n_pimonths <- df %>% filter(!is.na(parsed_install_month)) %>% nrow
n_pu1dates <- df %>% filter(!is.na(parsed_upgrade1_date)) %>% nrow
n_pu1months <- df %>% filter(!is.na(parsed_upgrade1_month)) %>% nrow
n_pu2dates <- df %>% filter(!is.na(parsed_upgrade2_date)) %>% nrow
n_pu2months <- df %>% filter(!is.na(parsed_upgrade2_month)) %>% nrow
# Perc of records with install or upgrade dates
perc_idates <- round(n_idates / nrow(df) * 100, 2)
perc_u1dates <- round(n_u1dates / nrow(df) * 100, 2)
perc_u2dates <- round(n_u2dates / nrow(df) * 100, 2)
# Perc of records with parsed dates and months
perc_pidates <- round(n_pidates / nrow(df) * 100, 2)
perc_pimonths <- round(n_pimonths / nrow(df) * 100, 2)
perc_pu1dates <- round(n_pu1dates / nrow(df) * 100, 2)
perc_pu1months <- round(n_pu1months / nrow(df) * 100, 2)
perc_pu2dates <- round(n_pu2dates / nrow(df) * 100, 2)
perc_pu2months <- round(n_pu2months / nrow(df) * 100, 2)
# Add to list
msg[[city]] <- glue(
"\n\n**Verified {city} Bikeways (n = {df %>% nrow}, 100%)**\n",
"\n* Install Dates: {n_idates} ({perc_idates}%)",
"\n\t* Parsable Dates: {n_pidates} ({perc_pidates}%)",
"\n \t* Parsable Months: {n_pimonths} ({perc_pimonths}%)",
"\n* Upgrade 1 Dates: {n_u1dates} ({perc_u1dates}%)",
"\n\t* Parsable Dates: {n_pu1dates} ({perc_pu1dates}%)",
"\n\t* Parsable Months: {n_pu1months} ({perc_pu1months}%)",
"\n* Upgrade 2 Dates: {n_u2dates} ({perc_u2dates}%)",
"\n\t* Parsable Dates: {n_pu2dates} ({perc_pu2dates}%)",
"\n\t* Parsable Months: {n_pu2months} ({perc_pu2months}%)\n\n"
)
df <- df %>% filter(
!is.na(verify_install_date) |
!is.na(verify_upgrade1_date) |
!is.na(verify_upgrade2_date)
)
parsed[[city]] <- data.frame(
orig_date = c(df$verify_install_date, df$verify_upgrade1_date, df$verify_upgrade2_date),
clean_date = c(df$clean_install_date, df$clean_upgrade1_date, df$clean_upgrade2_date),
parsed_date = c(df$parsed_install_date, df$parsed_upgrade1_date, df$parsed_upgrade2_date),
parsed_month = c(df$parsed_install_month, df$parsed_upgrade1_month, df$parsed_upgrade2_month)
)
parsed[[city]] <- parsed[[city]] %>%
group_by(orig_date) %>%
count() %>%
ungroup %>%
left_join(
parsed[[city]] %>%
distinct(orig_date, .keep_all = T),
by = "orig_date"
) %>%
arrange(desc(n)) %>%
filter(!is.na(orig_date))
}Verified Vancouver Bikeways (n = 745, 100%)
Verified Calgary Bikeways (n = 766, 100%)
Verified Toronto Bikeways (n = 326, 100%)